import numpy as np
import pandas as pd

from src.utils.config import config, logger
from src.mobile.model import mobile_model_config
from src.mobile.preprocessor import prop_preprocessor as prop
from src.utils.model_utils import cal_period, load_sku_property
import time
import scipy.stats as stats

# 手机SKU属性在redis中key的前缀
MOBILE_REDIS_PREFIX_KEY = config.get_config('project', 'mobile_redis_prefix_key')


def repeatData(df, size=3):
    X = df
    X=X.reset_index()
    # ind = np.arange(X.shape[0])
    dfsize = X.shape[0]
    logger.info('dfsize={}'.format(dfsize))
    if dfsize==0:
        return X
    ind = np.random.randint(0, high=dfsize, size=dfsize * (size - 1))
    for i in range(7):
        np.random.shuffle(ind)
    repeatDf = X.loc[ind]
    samples_offset = random_ratio(dfsize * (size - 1))
    repeatDf.item_quotation_price_num = repeatDf.item_quotation_price_num * samples_offset
    return repeatDf

def preprocess_model_data(data, is_cal_period=True):
    """
    预处理成模型数据
    :param data: 原始数据
    :param is_cal_period: 是否计算周期
    :return:
    """
    model_data = data.rename(columns=mobile_model_config.MOBILE_COLUMNS_MAPPING).copy()

    # 将memory字段为memory+storage形式的拆分为memory和storage字段
    memory_storage_split = model_data['memory'].str.split('+', expand=True)
    if memory_storage_split.shape[1] == 1:
        # 如果只分出来一个字段，那么补上一个
        memory_storage_split.columns = ['memory_tmp']
        memory_storage_split['storage_tmp'] = np.nan
    else:
        memory_storage_split.columns = ['memory_tmp', 'storage_tmp']
    model_data = pd.concat([model_data, memory_storage_split], axis=1, sort=False)
    model_data['memory'] = model_data['memory_tmp']
    model_data['storage'] = model_data['storage'].where(pd.isnull(model_data['storage_tmp']), model_data['storage_tmp'])
    model_data = model_data.drop(columns=['memory_tmp', 'storage_tmp'])

    # 将苹果手机的内存字段设置为特定字符以区分其他手机没有内存为unknown的情况
    model_data.loc[model_data['product_brand_name'] == '苹果', 'memory'] = prop.APPLE_MEMORY_FLAG
    # 对颜色和型号做交叉
    # model_data['body_color'] = np.where(model_data['color'] != 'unknown',
    #                                model_data['product_name'] + '_X_' + model_data['color'], 'unknown')
    model_data['body_color'] = np.where(model_data['color'] != 'unknown',
                                   model_data['color'], 'unknown')
    if is_cal_period:
        model_data['period'] = model_data['settle_list_create_date'].apply(cal_period, interval=3).astype(str)

    return model_data

def preprocess_rare_product_model_data_oversampling(data):
    """
    预处理成模型数据
    :param data: 原始数据
    :param is_cal_period: 是否计算周期
    :return:
    """
    product_color_list=mobile_model_config.GET_OVERSAMPLING_PRODUCT_ID
    product_list=list(product_color_list.keys())
    model_data = data
    add_data_df = pd.DataFrame()
    product_cnt_df=model_data.loc[model_data['product_id'].isin(product_list)].groupby('product_id')['product_id'].count().reset_index(name="cnt")
    product_cnt_df.count=product_cnt_df['cnt'].astype(int)
    match_product=product_cnt_df.loc[product_cnt_df.cnt<100].reset_index()
    size=match_product.shape[0]
    for i in range(size):
        row=match_product.loc[i]
        product_id=row.product_id
        color_map=product_color_list.get(product_id)
        match_product_model_data=model_data.loc[model_data.product_id==product_id].reset_index(drop=True)
        # color_str=product_coloc_list.get(product_id)
        # color_list=color_str.split('_')
        dict_df=match_product_model_data.set_index(['product_no','product_level_name','product_name','settle_list_create_date'])['item_quotation_price_num'].to_dict()
        logger.info('oversampling product_id={},datasize={},df={}'.format(product_id,row.cnt,dict_df))

        random_index = np.random.randint(0, row.cnt, size=100-row.cnt)
        # color_index = np.random.randint(0, len(color_map), size=mobile_model_config.OVERSAMPLING - row.cnt)
        # color_list=[color_map.get(value) for value in color_index]
        add_data=match_product_model_data.loc[random_index]
        # add_data.body_color=color_list
        samples_offset=random_ratio(100-row.cnt)
        add_data.item_quotation_price_num=add_data.item_quotation_price_num*samples_offset

        add_data_df=add_data_df.append(add_data,ignore_index=True)
    model_data=model_data.append(add_data_df, ignore_index=True)

    return model_data


def random_ratio(num):
  # logger.info('随机生成折扣')
  lower, upper = -0.01, 0.01
  mu, sigma = 0.0, 0.005
  X = stats.truncnorm((lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
  samples = X.rvs(num)
  samples = samples + 1
  return samples

def process_predict_data(data, process_level=True):
    """
    预处理传入的预测数据
    :param data: 数据
    :param process_level: 是否处理等级
    :return:
    """
    logger.info('processing predict data')
    # sku_property = load_sku_property(data, MOBILE_REDIS_PREFIX_KEY, mobile_model_config.MOBILE_COLUMNS_MAPPING)
    t0=time.time()
    try:
        ti1 = time.time()
        # res_predict['history_avg_price'] = load_history_avg_price_batch(mobile_model_config.HISTORY_AVG_PRICE_NAME,res_predict['key'].values)
        sku_property = load_sku_property(data, MOBILE_REDIS_PREFIX_KEY, mobile_model_config.MOBILE_COLUMNS_MAPPING)
        logger.info('load_sku_property use time @{}'.format(time.time() - ti1))
    except Exception as e:
        logger.info('load_sku_property timeout@{}'.format(e))
        sku_property=[]
    logger.info('load_sku_property use time@{}'.format(time.time() - t0))

    if sku_property is None or len(sku_property)==0:
        predict_data = pd.DataFrame()
        return predict_data

    # 检查特征是否完整
    predict_data = pd.DataFrame(sku_property)
    for feature in mobile_model_config.MOBILE_FEATURES_NEW:
        if feature not in predict_data:
            predict_data[feature] = 'unknown'
    # 检查是否有product_id，如果没有，增加product_id，默认为0
    if 'product_id' not in predict_data:
        predict_data['product_id'] = 0
    # 将缺失值用unknown填补
    predict_data.fillna('unknown', inplace=True)
    predict_data['product_level_template_id'] = predict_data['product_level_template_id'].astype(str)

    if process_level:
        predict_data['product_level_name'] = predict_data['level_id'].copy()
        predict_data['product_level_name'] = predict_data['product_level_name'].replace(
            mobile_model_config.MOBILE_LEVEL_ID_MAPPING).astype(str)
    logger.info('preprocess model data')
    predict_data = preprocess_model_data(predict_data, is_cal_period=False)

    return predict_data
